/**
 * @file SerialStrategy.cpp
 * @brief 串口通信策略实现
 * @author Your Name
 * @date 2025-03-30
 */

#include "SerialStrategy.h"
#include <QDebug>

SerialStrategy::SerialStrategy(QObject *parent)
    : ICommunicationStrategy(parent), m_lastConnectedState(false) {

    // 配置连接检测定时器
    m_connectionCheckTimer.setInterval(1000); // 1秒检测一次
    connect(&m_connectionCheckTimer, &QTimer::timeout,
            this, &SerialStrategy::checkConnection);

    // 连接串口信号
    connect(&m_serialPort, &QSerialPort::readyRead,
            this, &SerialStrategy::handleReadyRead);
    connect(&m_serialPort, &QSerialPort::errorOccurred,
            this, &SerialStrategy::handleError);
}

SerialStrategy::~SerialStrategy() {
    close();
}

bool SerialStrategy::init(const QVariantMap& config) {
    // 保存配置
    m_config = config;

    // 检查关键参数是否存在
    if (!config.contains("port") || !config.contains("baudRate")) {
        emit errorOccurred(-1, "串口配置缺少必要参数");
        return false;
    }

    // 配置串口参数
    m_serialPort.setPortName(config["port"].toString());
    m_serialPort.setBaudRate(config["baudRate"].toInt());

    // 配置数据位
    if (config.contains("dataBits")) {
        QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(config["dataBits"].toInt());
        m_serialPort.setDataBits(dataBits);
    } else {
        m_serialPort.setDataBits(QSerialPort::Data8); // 默认8位数据位
    }

    // 配置校验位
    if (config.contains("parity")) {
        QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(config["parity"].toInt());
        m_serialPort.setParity(parity);
    } else {
        m_serialPort.setParity(QSerialPort::NoParity); // 默认无校验
    }

    // 配置停止位
    if (config.contains("stopBits")) {
        QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(config["stopBits"].toInt());
        m_serialPort.setStopBits(stopBits);
    } else {
        m_serialPort.setStopBits(QSerialPort::OneStop); // 默认1位停止位
    }

    // 配置流控
    if (config.contains("flowControl")) {
        QSerialPort::FlowControl flowControl = static_cast<QSerialPort::FlowControl>(config["flowControl"].toInt());
        m_serialPort.setFlowControl(flowControl);
    } else {
        m_serialPort.setFlowControl(QSerialPort::NoFlowControl); // 默认无流控
    }

    qInfo() << "串口策略初始化完成:" << m_serialPort.portName() << "波特率:" << m_serialPort.baudRate();
    return true;
}

bool SerialStrategy::open() {
    // 如果已经打开，先关闭
    if (m_serialPort.isOpen()) {
        m_serialPort.close();
    }

    // 尝试打开串口
    bool success = m_serialPort.open(QIODevice::ReadWrite);

    if (success) {
        qInfo() << "串口" << m_serialPort.portName() << "打开成功";
        m_lastConnectedState = true;
        emit connectionChanged(true);

        // 开始连接检测
        m_connectionCheckTimer.start();
    } else {
        qWarning() << "串口打开失败:" << m_serialPort.errorString();
        emit errorOccurred(-2, "串口打开失败: " + m_serialPort.errorString());
    }

    return success;
}

void SerialStrategy::close() {
    // 停止连接检测
    m_connectionCheckTimer.stop();

    // 关闭串口
    if (m_serialPort.isOpen()) {
        m_serialPort.close();
        qInfo() << "串口" << m_serialPort.portName() << "已关闭";

        // 更新连接状态
        if (m_lastConnectedState) {
            m_lastConnectedState = false;
            emit connectionChanged(false);
        }
    }
}

qint64 SerialStrategy::send(const QByteArray& data) {
    // 检查连接状态
    if (!isConnected()) {
        emit errorOccurred(-3, "串口未连接，无法发送数据");
        return -1;
    }

    // 发送数据
    qint64 bytesWritten = m_serialPort.write(data);

    if (bytesWritten == -1) {
        qWarning() << "串口数据发送失败:" << m_serialPort.errorString();
        emit errorOccurred(-4, "串口数据发送失败: " + m_serialPort.errorString());
    } else if (bytesWritten != data.size()) {
        qWarning() << "串口数据发送不完整, 已发送:" << bytesWritten << "总大小:" << data.size();
        emit errorOccurred(-5, "串口数据发送不完整");
    } else {
        // 确保数据立即发送
        m_serialPort.flush();
        qDebug() << "串口成功发送" << bytesWritten << "字节数据";
    }

    return bytesWritten;
}

bool SerialStrategy::isConnected() const {
    return m_serialPort.isOpen();
}

QList<QSerialPortInfo> SerialStrategy::getAvailablePorts() {
    return QSerialPortInfo::availablePorts();
}

void SerialStrategy::handleReadyRead() {
    // 读取所有可用数据
    QByteArray data = m_serialPort.readAll();

    if (!data.isEmpty()) {
        qDebug() << "串口接收到" << data.size() << "字节数据";
        emit dataReceived(data);
    }
}

void SerialStrategy::handleError(QSerialPort::SerialPortError error) {
    // 忽略串口已关闭或无错误的情况
    if (error == QSerialPort::NoError ||
        (error == QSerialPort::NotOpenError && !m_lastConnectedState)) {
        return;
    }

    QString errorMsg = "串口错误: ";

    switch (error) {
        case QSerialPort::DeviceNotFoundError:
            errorMsg += "设备未找到";
            break;
        case QSerialPort::PermissionError:
            errorMsg += "权限错误，可能被其他程序占用";
            break;
        case QSerialPort::OpenError:
            errorMsg += "打开失败";
            break;
        case QSerialPort::WriteError:
            errorMsg += "写入错误";
            break;
        case QSerialPort::ReadError:
            errorMsg += "读取错误";
            break;
        case QSerialPort::ResourceError:
            errorMsg += "资源错误，设备可能已断开";
            break;
        case QSerialPort::TimeoutError:
            errorMsg += "操作超时";
            break;
        default:
            errorMsg += "未知错误: " + QString::number(error);
            break;
    }

    qWarning() << errorMsg;
    emit errorOccurred(error, errorMsg);

    // 如果是资源错误，可能是设备断开，需要关闭端口并发送连接状态变化
    if (error == QSerialPort::ResourceError) {
        if (m_serialPort.isOpen()) {
            m_serialPort.close();
        }

        if (m_lastConnectedState) {
            m_lastConnectedState = false;
            emit connectionChanged(false);
        }
    }
}

void SerialStrategy::checkConnection() {
    bool currentState = m_serialPort.isOpen();

    // 连接状态发生变化时发送信号
    if (currentState != m_lastConnectedState) {
        m_lastConnectedState = currentState;
        emit connectionChanged(currentState);

        if (currentState) {
            qInfo() << "串口连接已恢复";
        } else {
            qWarning() << "串口连接已断开";
        }
    }
}
